package edu.nf.project.services.storeOperation.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.Update;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import edu.nf.project.entitys.dto.storeOperation.CustomerOrderDetailsDTO;
import edu.nf.project.entitys.dto.storeOperation.OrderDTO;
import edu.nf.project.entitys.dto.storeOperation.OrderItemDTO;
import edu.nf.project.entitys.dto.storeOperation.COrder_ItemDTO;
import edu.nf.project.entitys.entity.accountsAndPermissions.convention.Users;
import edu.nf.project.entitys.entity.employeeAndCustomerInformation.relevancy.CustomerInfo_Coupon;
import edu.nf.project.entitys.entity.storeOperation.convention.dish.Dish;
import edu.nf.project.entitys.entity.storeOperation.convention.operate.Board;
import edu.nf.project.entitys.entity.storeOperation.convention.operate.CustomerOrder;
import edu.nf.project.entitys.entity.storeOperation.convention.operate.CustomerOrderItem;
import edu.nf.project.entitys.enums.storeOperation.BoardStatusEnum;
import edu.nf.project.entitys.enums.storeOperation.OrderStatusEnum;
import edu.nf.project.entitys.enums.storeOperation.OrderTypeEnum;
import edu.nf.project.mappers.accountsAndPermissions.convention.UsersMapper;
import edu.nf.project.mappers.employeeAndCustomerInformation.relevancy.CustomerInfo_CouponMapper;
import edu.nf.project.mappers.storeOperation.convention.BoardMapper;
import edu.nf.project.mappers.storeOperation.convention.CustomerOrderMapper;
import edu.nf.project.mappers.storeOperation.convention.CustomerOrderItemMapper;
import edu.nf.project.mappers.storeOperation.convention.DishMapper;
import edu.nf.project.services.process.OrderProcess;
import edu.nf.project.services.storeOperation.CustomerOrderService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 */
@Service
public class CustomerOrderServiceImpl implements CustomerOrderService {
    @Autowired
    private CustomerOrderMapper customerOrderMapper;

    @Autowired
    private BoardMapper boardMapper;

    @Autowired
    private CustomerOrderItemMapper customerOrderItemMapper;

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private CustomerInfo_CouponMapper infoCouponMapper;

    @Autowired
    private OrderProcess orderProcess;

    @Override
    @Transactional
    public Integer createOrder(CustomerOrder order) {
        // 设置订单状态为待支付
        order.setOrderStatus(OrderStatusEnum.TO_BE_PAID);
        // 设置下单时间
        order.setPlaceOrderTime(new Date());
        // 插入订单
        int result = customerOrderMapper.insert(order);
        if (result > 0) {
            return order.getOrderId();
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createOrderAndItem(OrderDTO orderDTO) {
        // 1. 插入订单主表
        CustomerOrder order = orderDTO.getOrder();

        CustomerOrder oldOrder = new CustomerOrder(order);

        Integer oldOrderId = order.getOrderId();
        //对订单主表的添加/修改
        //如果订单不存在那么就将订单信息添加，否则就只根据订单编号添加订单项数据
        //异常抛出
        validateOrderDTO(orderDTO);
        orderProcess.processOrder(order);

        Integer orderId = order.getOrderId();
        // 2. 处理订单项
        //接收到的订单项
        List<CustomerOrderItem> orderItems = orderDTO.getOrderItems();

        //查找到所有该订单的订单项
        List<CustomerOrderItem> orderItemsAll = getItems(orderId);

        //订单项操作
        orderProcess.processOrderItems(orderItems, orderItemsAll, orderId);

        if (oldOrderId == null) {
            handleExtensionLogic(oldOrder,orderDTO);
        }
        return orderId;
    }

    private void validateOrderDTO(OrderDTO orderDTO) {
        if (orderDTO == null || orderDTO.getOrder() == null || orderDTO.getOrder().getUId() == null) {
            throw new IllegalArgumentException("订单或用户 ID 不能为空");
        }
    }

    private void handleExtensionLogic(CustomerOrder order, OrderDTO orderDTO) {
        if (order.getOrderId() == null && order.getBoardId() != null) {
            orderProcess.handlerBoardStatus(order.getBoardId());
        }
        orderProcess.handlerCoupon(orderDTO.getCouponId(), order.getUId());
    }

    @Override
    public Page<CustomerOrder> getOrderList(Page<CustomerOrder> page, Integer orderStatus) {
        LambdaQueryWrapper<CustomerOrder> queryWrapper = new LambdaQueryWrapper<>();
        // 根据订单状态筛选
        if (orderStatus != null) {
            queryWrapper.eq(CustomerOrder::getOrderStatus, OrderStatusEnum.values()[orderStatus]);
        }
        // 按下单时间倒序排序
        queryWrapper.orderByDesc(CustomerOrder::getPlaceOrderTime);
        return customerOrderMapper.selectPage(page, queryWrapper);
    }

    @Override
    public CustomerOrder getOrderInfo(Integer orderId) {
        // 查询订单基本信息
        return customerOrderMapper.selectById(orderId);
    }

    @Override
    @Transactional
    public boolean updateOrderStatus(Integer orderId, Integer orderStatus) {
        CustomerOrder order = new CustomerOrder();
        order.setOrderId(orderId);
        order.setOrderStatus(OrderStatusEnum.values()[orderStatus]);
        // 如果状态为已支付，设置支付时间
        if (orderStatus == OrderStatusEnum.PAID.ordinal()) {
            order.setPaymentTime(new Date());
        }
        return customerOrderMapper.updateById(order) > 0;
    }

    @Override
    public List<CustomerOrderDetailsDTO> getOrdersByRegion(Integer[] regionIds) {
        // 1. 获取指定区域下的所有餐桌ID
        LambdaQueryWrapper<Board> boardWrapper = new LambdaQueryWrapper<>();
        boardWrapper.in(Board::getRegionId, regionIds);
        List<Board> boards = boardMapper.selectList(boardWrapper);

        if (boards.isEmpty()) {
            return List.of();
        }

        // 2. 根据餐桌ID列表查询订单
        List<Integer> boardIds = boards.stream()
                .map(Board::getBoardId)
                .toList();

        LambdaQueryWrapper<CustomerOrder> orderWrapper = new LambdaQueryWrapper<>();
        orderWrapper.in(CustomerOrder::getBoardId, boardIds)
                .orderByDesc(CustomerOrder::getPlaceOrderTime);

        List<CustomerOrder> orders = customerOrderMapper.selectList(orderWrapper);

        if (orders.isEmpty()) {
            return List.of();
        }

        // 3. 获取订单中涉及的餐桌和用户ID
        List<Integer> involvedBoardIds = orders.stream()
                .map(CustomerOrder::getBoardId)
                .distinct()
                .toList();
        List<Integer> involvedUserIds = orders.stream()
                .map(CustomerOrder::getUId)
                .distinct()
                .toList();

        // 4. 批量查询餐桌信息和用户信息
        Map<Integer, Board> boardMap = boardMapper.selectBatchIds(involvedBoardIds).stream()
                .collect(Collectors.toMap(Board::getBoardId, board -> board));
        Map<Integer, Users> userMap = usersMapper.selectBatchIds(involvedUserIds).stream()
                .collect(Collectors.toMap(Users::getUId, user -> user));

        // 5. 组装 DTO
        List<CustomerOrderDetailsDTO> result = new ArrayList<>();
        for (CustomerOrder order : orders) {
            CustomerOrderDetailsDTO dto = new CustomerOrderDetailsDTO();

            // 将 CustomerOrder 的属性值赋给 CustomerOrderDetailsDTO
            dto.setOrderId(order.getOrderId());
            dto.setBoardId(order.getBoardId());
            dto.setUId(order.getUId());

            // 使用正确的字段名和setter
            dto.setTotalAmount(order.getTotalAmount()); // 将 totalAmount 赋值给 totalAmount
            dto.setDiscountAmount(order.getDiscountAmount());
            dto.setPayableAmount(order.getPayableAmount()); // 将 payableAmount 赋值给 payableAmount
            dto.setOrderStatus(order.getOrderStatus());
            dto.setPlaceOrderTime(order.getPlaceOrderTime());
            dto.setPaymentTime(order.getPaymentTime());
            dto.setRemark(order.getRemark());
            dto.setOrderType(order.getOrderType()); // 添加对 OrderTypeEnum 的赋值
            dto.setShippingAddress(order.getShippingAddress()); // 添加对 shippingAddress 的赋值

            // 设置餐桌名称
            Board board = boardMap.get(order.getBoardId());
            if (board != null) {
                dto.setBoardName(board.getBoardName());
            } else {
                dto.setBoardName("未知餐桌"); // 或者其他默认值
            }

            // 设置操作人名称
            Users user = userMap.get(order.getUId());
            if (user != null) {
                dto.setOperatorName(user.getUName());
            } else {
                dto.setOperatorName("未知操作人"); // 或者其他默认值
            }

            result.add(dto);
        }

        return result;
    }

    @Override
    public List<OrderItemDTO> getOrderItems(Integer orderId) {
        // 1. 获取订单项列表
        LambdaQueryWrapper<CustomerOrderItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerOrderItem::getOrderId, orderId);
        List<CustomerOrderItem> orderItems = customerOrderItemMapper.selectList(queryWrapper);

        if (orderItems.isEmpty()) {
            return List.of();
        }

        // 2. 获取所有菜品ID
        List<Integer> dishIds = orderItems.stream()
                .map(CustomerOrderItem::getDishId)
                .toList();

        // 3. 查询菜品信息
        LambdaQueryWrapper<Dish> dishWrapper = new LambdaQueryWrapper<>();
        dishWrapper.in(Dish::getDishId, dishIds);
        List<Dish> dishes = dishMapper.selectList(dishWrapper);

        // 4. 组装DTO
        List<OrderItemDTO> result = new ArrayList<>();
        for (CustomerOrderItem orderItem : orderItems) {
            Dish dish = dishes.stream()
                    .filter(d -> d.getDishId().equals(orderItem.getDishId()))
                    .findFirst()
                    .orElse(null);
            if (dish != null) {
                result.add(new OrderItemDTO(orderItem, dish));
            }
        }

        return result;
    }

    @Override
    public List<CustomerOrderItem> getItems(Integer orderId) {
        LambdaQueryWrapper<CustomerOrderItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerOrderItem::getOrderId, orderId);
        //查找到所有该订单的订单项
        return customerOrderItemMapper.selectList(queryWrapper);
    }

    @Override
    public List<COrder_ItemDTO> getOrdersByDate(String date) {
        // 1. 构建订单查询条件
        LambdaQueryWrapper<CustomerOrder> orderWrapper = new LambdaQueryWrapper<>();
        
        if (date != null && !date.trim().isEmpty()) {
            // 指定日期时，查询该日期当天的订单
            // 假设placeOrderTime字段存储的是完整的日期时间
            // 需要查询指定日期00:00:00到23:59:59之间的订单
            try {
                // 解析日期字符串，格式为 yyyy-MM-dd
                String startDate = date + " 00:00:00";
                String endDate = date + " 23:59:59";
                
                orderWrapper.ge(CustomerOrder::getPlaceOrderTime, startDate)
                           .le(CustomerOrder::getPlaceOrderTime, endDate);
            } catch (Exception e) {
                throw new IllegalArgumentException("日期格式错误，请使用 yyyy-MM-dd 格式");
            }
        }

        orderWrapper.orderByAsc(CustomerOrder::getPlaceOrderTime);
        
        List<CustomerOrder> orders = customerOrderMapper.selectList(orderWrapper);
        
        if (orders.isEmpty()) {
            return List.of();
        }

        // 2. 获取所有订单ID
        List<Integer> orderIds = orders.stream()
                .map(CustomerOrder::getOrderId)
                .toList();

        // 3. 查询所有订单项
        LambdaQueryWrapper<CustomerOrderItem> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.in(CustomerOrderItem::getOrderId, orderIds);
        List<CustomerOrderItem> allOrderItems = customerOrderItemMapper.selectList(itemWrapper);

        if (allOrderItems.isEmpty()) {
            // 如果没有订单项，只返回订单信息
            List<COrder_ItemDTO> result = new ArrayList<>();
            for (CustomerOrder order : orders) {
                COrder_ItemDTO dto = new COrder_ItemDTO();
                dto.setCustomerOrder(order);
                dto.setCustomerOrderItem(null);
                dto.setDishes(List.of());
                result.add(dto);
            }
            return result;
        }

        // 4. 获取所有菜品ID
        List<Integer> dishIds = allOrderItems.stream()
                .map(CustomerOrderItem::getDishId)
                .distinct()
                .toList();

        // 5. 查询菜品信息
        LambdaQueryWrapper<Dish> dishWrapper = new LambdaQueryWrapper<>();
        dishWrapper.in(Dish::getDishId, dishIds);
        List<Dish> dishes = dishMapper.selectList(dishWrapper);

        // 6. 创建菜品ID到菜品对象的映射
        Map<Integer, Dish> dishMap = dishes.stream()
                .collect(Collectors.toMap(Dish::getDishId, dish -> dish));

        // 7. 按订单ID分组订单项
        Map<Integer, List<CustomerOrderItem>> orderItemsMap = allOrderItems.stream()
                .collect(Collectors.groupingBy(CustomerOrderItem::getOrderId));

        // 8. 组装 COrder_ItemDTO
        List<COrder_ItemDTO> result = new ArrayList<>();
        for (CustomerOrder order : orders) {
            List<CustomerOrderItem> orderItems = orderItemsMap.get(order.getOrderId());
            
            if (orderItems != null && !orderItems.isEmpty()) {
                // 如果订单有订单项，为每个订单项创建一个DTO
                for (CustomerOrderItem orderItem : orderItems) {
                    COrder_ItemDTO dto = new COrder_ItemDTO();
                    dto.setCustomerOrder(order);
                    dto.setCustomerOrderItem(orderItem);
                    
                    // 获取对应的菜品信息
                    Dish dish = dishMap.get(orderItem.getDishId());
                    if (dish != null) {
                        dto.setDishes(List.of(dish));
                    } else {
                        dto.setDishes(List.of());
                    }
                    
                    result.add(dto);
                }
            } else {
                // 如果订单没有订单项，创建一个只有订单信息的DTO
                COrder_ItemDTO dto = new COrder_ItemDTO();
                dto.setCustomerOrder(order);
                dto.setCustomerOrderItem(null);
                dto.setDishes(List.of());
                result.add(dto);
            }
        }

        return result;
    }

    @Override
    public List<CustomerOrder> listCanRefundOrder(Integer uId) {
        //当前时间减去1小时
        Date oneHourAgo = Date.from(LocalDateTime.now().minusHours(1).atZone(ZoneId.systemDefault()).toInstant());
        return customerOrderMapper.listCanRefundOrder(uId, oneHourAgo);
    }


} 